#include "UdpClient.hpp"
#include <sys/types.h>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <signal.h>
#include "Common.hpp"


int sockfd = -1;

struct sockaddr_in server;
void ClientQuit(int signo)
{
	(void)signo;

	const std::string quit = "QUIT";
	int n = ::sendto(sockfd, quit.c_str(), quit.size(), 0, CONV(&server), sizeof(server));

	exit(0);
}

// 线程不断从同一个文件描述符读取消息并打印
void *Recver(void *args)
{
	while (1)
	{
		struct sockaddr_in temp;
		socklen_t len = sizeof(temp);
		char buffer[1024];
		int n = ::recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, CONV(&temp), &len);
		if (n > 0)
		{
			buffer[n] = 0;
			std::cout << buffer << std::endl;
		}
	}
}

// 客户端要拿到服务端的ip和port
int main(int argc, char *argv[])
{
	if (argc != 3)
	{
		std::cerr << "Usage: " << argv[0] << "serverip serverport" << std::endl;
		Die(USAGE_ERR);
	}
	signal(2,ClientQuit);

	std::string serverip = argv[1];
	uint16_t serverport = std::stoi(argv[2]);

	// 1.创建套接字
	sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);
	if (sockfd < 0)
	{
		std::cerr << "socket error" << std::endl;
		Die(SOCKET_ERR);
	}

	// 1.1 填充server信息
	memset(&server, 0, sizeof(server));
	server.sin_family = AF_INET;
	server.sin_port = htons(serverport);
	server.sin_addr.s_addr = ::inet_addr(serverip.c_str());


	// 1.2 启动的时候，给服务器推送消息即可
	const std::string online = "...来了";
	int n = ::sendto(sockfd, online.c_str(), online.size(), 0, CONV(&server), sizeof(server));

	// 创建线程，接收消息
	pthread_t tid;
	pthread_create(&tid, nullptr, Recver, nullptr);

	// 主线程获取用户输入，并把用户输入发送回去
	while (1)
	{
		std::cout << "please enter:";
		std::string message;
		std::getline(std::cin, message);

		int n = ::sendto(sockfd, message.c_str(), message.size(), 0, CONV(&server), sizeof(server));
		(void)n;

		// 收消息用新线程，不然只能发一条收一条

		// struct sockaddr_in temp;
		// socklen_t len = sizeof(temp);
		// char buffer[1024];
		// n = ::recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, CONV(&temp), &len);
		// if (n > 0)
		// {
		// 	buffer[n] = 0;
		// 	std::cout << buffer << std::endl;
		// }
	}

	return 0;
}